/*
 * Copyright (C) 2003, Velocityme Partnership
 * SetupSessionBean.java
 *
 * Created on 26 April 2003, 06:07
 */

package com.velocityme.session;

import com.velocityme.entity.ChangeDeltaItemTypeBean;
import com.velocityme.entity.ChangeDeltaTypeBean;
import com.velocityme.entity.LoginStatusBean;
import com.velocityme.entity.NotificationMechanismBean;
import com.velocityme.entity.PermissionBean;
import javax.ejb.*;
import javax.naming.*;
import java.util.*;
import com.velocityme.interfaces.*;
import com.velocityme.utility.PasswordEncrypter;
import com.velocityme.valueobjects.*;
import java.rmi.RemoteException;

/**
 *
 * @author  Robert Crida Work
 * @ejb.bean
 *           type="Stateless"
 *           cmp-version="2.x"
 *           name="SetupSession"
 *           jndi-name="ejb/SetupSession"
 *           view-type="both"
 *           transaction-type="Container"
 * @ejb.transaction type="Required"
 *
 * @ejb.util generate="physical"
 */
public class SetupSessionBean implements SessionBean {
    
    private SessionContext m_context;
    
    /**
     * Check if the database has already been initialised
     *
     * @ejb.interface-method view-type="local"
     */
    public boolean isLicenceInstalled() {
        try {
            Collection licenceKeyLocals = LicenceKeyUtil.getLocalHome().findAll();
            if (licenceKeyLocals.size() > 0)
                return true;
            else {
                // make sure that the client GUID exists
                SystemPropertyLocalHome systemPropertyLocalHome = SystemPropertyUtil.getLocalHome();
                try {
                    systemPropertyLocalHome.findByName("client.guid");
                } catch(FinderException e) {
                    // we didn't find it so create one
                    systemPropertyLocalHome.create(new SystemPropertyValue(new Integer(0), "client.guid", SystemPropertyUtil.generateGUID(this), false, false));
                }
                return false;
            }
        } catch(NamingException e) {
            throw new EJBException(e);
        } catch(FinderException e) {
            throw new EJBException(e);
        } catch(CreateException e) {
            throw new EJBException(e);
        }
    }
    
    /**
     * Creates the root node containing default role and default user assigned to the role.
     * Also sets up the permissions.
     *
     * @param p_username Default username
     * @param p_password Default setup user password
     *
     * @ejb.interface-method view-type="remote"
     **/
    public boolean setupSystemNew(java.lang.String p_username, java.lang.String p_password) {
        try {
            // make sure that all the constant tables contain everything necessary
            setupConstantTables();
            // then do the rest!
            DBObjectLocalHome dBObjectLocalHome = DBObjectUtil.getLocalHome();
            NodeLocalHome nodeLocalHome = NodeUtil.getLocalHome();
            ContactableLocalHome contactableLocalHome = ContactableUtil.getLocalHome();
            OrganisationLocalHome organisationLocalHome = OrganisationUtil.getLocalHome();
            DepartmentLocalHome departmentLocalHome = DepartmentUtil.getLocalHome();
            PersonLocalHome personLocalHome = PersonUtil.getLocalHome();
            UserLocalHome userLocalHome = UserUtil.getLocalHome();
            NotificationMechanismLocalHome notificationMechanismLocalHome = NotificationMechanismUtil.getLocalHome();
            ContactDetailTypeLocalHome contactDetailTypeLocalHome = ContactDetailTypeUtil.getLocalHome();
            PermissionLocalHome permissionLocalHome = PermissionUtil.getLocalHome();
            RoleLocalHome roleLocalHome = RoleUtil.getLocalHome();
            SystemPropertyLocalHome systemPropertyLocalHome = SystemPropertyUtil.getLocalHome();
            Integer id = new Integer(0);
            // if root already exists then exit
            try {
                NodeLocal nodeLocal = nodeLocalHome.findRoot();
                // if the root exists then we mustn't do anything
                return false;
            }
            catch(FinderException e) {
                // this is thrown if the root doesn't exist, we must continue and populate
            }
            // create root
            DBObjectLocal rootDBObjectLocal = dBObjectLocalHome.create();
            NodeLocal rootNodeLocal = nodeLocalHome.create(rootDBObjectLocal, new NodeValue(id, "Root", "The root node of the tree", "Node", "SystemNode"));
            // create directory
            DBObjectLocal directoryDBObjectLocal = dBObjectLocalHome.create();
            NodeLocal directoryNodeLocal = nodeLocalHome.create(directoryDBObjectLocal, new NodeValue(id, "Directory", "", "Node", "Directory"), rootNodeLocal);
            // create default organisation
            DBObjectLocal defaultOrganisationDBObjectLocal = dBObjectLocalHome.create();
            NodeLocal defaultOrganisationNodeLocal = nodeLocalHome.create(defaultOrganisationDBObjectLocal, new NodeValue(id, "Default Organisation", "Default organisation", "Contactable", "Organisation"), rootNodeLocal);
            ContactableLocal defaultOrgContactableLocal = contactableLocalHome.create(defaultOrganisationNodeLocal, new ContactableValue(id, "Organisation"));
            OrganisationLocal defaultOrganisationLocal = organisationLocalHome.create(defaultOrgContactableLocal, new OrganisationValue(id));
            // create default department
            DBObjectLocal defaultDepartmentDBObjectLocal = dBObjectLocalHome.create();
            NodeLocal defaultDepartmentNodeLocal = nodeLocalHome.create(defaultDepartmentDBObjectLocal, new NodeValue(id, "Default Department", "Default department", "Contactable", "Department"), rootNodeLocal);
            ContactableLocal defaultDepContactableLocal = contactableLocalHome.create(defaultDepartmentNodeLocal, new ContactableValue(id, "Department"));
            DepartmentLocal defaultDepartmentLocal = departmentLocalHome.create(defaultDepContactableLocal, new DepartmentValue(id, "Default organisation::Default department"));
            // create system default person
            DBObjectLocal defaultPersonDBObjectLocal = dBObjectLocalHome.create();
            NodeLocal defaultPersonNodeLocal = nodeLocalHome.create(defaultPersonDBObjectLocal, new NodeValue(id, "Default Person", "Default person used for database setup", "Contactable", "Person"), rootNodeLocal);
            ContactableLocal defaultPerContactableLocal = contactableLocalHome.create(defaultPersonNodeLocal, new ContactableValue(id, "Person"));
            PersonValue personValue = new PersonValue(id, "Default Person", "", "Initial Configuration");
            PersonLocal defaultPersonLocal = personLocalHome.create(defaultPerContactableLocal, personValue);
            // create system default user
            DBObjectLocal defaultUserDBObjectLocal = dBObjectLocalHome.create();
            NodeLocal defaultUserNode = nodeLocalHome.create(defaultUserDBObjectLocal, new NodeValue(id, p_username, "Default user used database setup", "User", "User"), rootNodeLocal);
            UserValue userValue = new UserValue(id, p_username, Boolean.TRUE, Boolean.TRUE);
            userValue.setPersonValue(defaultPersonLocal.getPersonValue());
            UserLocal defaultUserLocal = userLocalHome.create(defaultUserNode, userValue);
            defaultUserLocal.setPassword(PasswordEncrypter.getInstance().encrypt(p_password));
            // generate default contact detail types
            ContactDetailTypeLocal contactDetailTypeLocal = contactDetailTypeLocalHome.create(new ContactDetailTypeValue(id, "Email", Boolean.TRUE, Boolean.TRUE, new Integer(0)));
            contactDetailTypeLocal.setNotificationMechanismLocal(notificationMechanismLocalHome.findByName("Email"));
            // generate permission set for system setup role
            Set permissionsLocal = new HashSet();
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.DEPARTMENT_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.DEPARTMENT_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.ORGANISATION_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.ORGANISATION_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.PERSON_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.PERSON_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.USER_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.USER_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.USER_ENABLE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.USER_CHANGE_PASSWORD))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.GROUP_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.GROUP_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.CONTACT_DETAIL_TYPE_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.ROLE_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.ROLE_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.USER_ACCESS_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.USER_ACCESS_DELETE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.GROUP_ACCESS_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.GROUP_ACCESS_DELETE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.ACTION_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.ACTION_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.NODE_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.NODE_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.NODE_DELETE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.TASK_CHANGE_STATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.PROJECT_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.PROJECT_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.TASK_TYPE_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.TASK_TYPE_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.STATE_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.STATE_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.STATUS_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.STATUS_EDIT))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.ISSUE_CREATE))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.NODE_VIEW))));
            permissionsLocal.add(permissionLocalHome.findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.SYSTEM_PROPERTY_EDIT))));
            // create default setup role
            DBObjectLocal defaultRoleDBObjectLocal = dBObjectLocalHome.create();
            NodeLocal defaultRoleNodeLocal = nodeLocalHome.create(defaultRoleDBObjectLocal, new NodeValue(id, "Default Setup", "Role used for setting up the database", "Role", "Role"), rootNodeLocal);
            RoleLocal defaultRoleLocal = roleLocalHome.create(defaultRoleNodeLocal, new RoleValue(id, new Boolean(true)), permissionsLocal);
            // create default system properties
            systemPropertyLocalHome.create(new SystemPropertyValue(id, "email.from.address", "you@your.address", false, true));
            systemPropertyLocalHome.create(new SystemPropertyValue(id, "email.internet.url", "https://internet.server.address:443", false, true));
            systemPropertyLocalHome.create(new SystemPropertyValue(id, "email.intranet.url", "http://intranet.server.address", false, true));
            systemPropertyLocalHome.create(new SystemPropertyValue(id, "email.account", "", false, true));
            systemPropertyLocalHome.create(new SystemPropertyValue(id, "email.account.username", "username", false, true));
            systemPropertyLocalHome.create(new SystemPropertyValue(id, "email.account.password", "password", true, true));
            systemPropertyLocalHome.create(new SystemPropertyValue(id, "file.attachment.home", "./", false, true));
            systemPropertyLocalHome.create(new SystemPropertyValue(id, "owner.organisation", "Your organisation", false, true));
            systemPropertyLocalHome.create(new SystemPropertyValue(id, "owner.organisation.url", "http://organisation.web.address", false, true));
            setupUserAccess(rootNodeLocal, defaultUserLocal, defaultRoleLocal);
            return true;
        }
        catch(NamingException e) {
            throw new EJBException(e);
        }
        catch(CreateException e) {
            throw new EJBException(e);
        }
        catch(FinderException e) {
            throw new EJBException(e);
        }
        catch(com.velocityme.interfaces.ServiceUnavailableException e) {
            throw new EJBException(e);
        }
    }
    
    private static void setupUserAccess(NodeLocal p_rootNodeLocal, UserLocal p_userLocal, RoleLocal p_roleLocal) throws NamingException, CreateException {
        DBObjectLocalHome dBObjectLocalHome = DBObjectUtil.getLocalHome();
        UserAccessLocalHome userAccessLocalHome = UserAccessUtil.getLocalHome();
        
        // assign user to this role in root node
        UserAccessLocal userAccessLocal = userAccessLocalHome.create(p_rootNodeLocal, p_userLocal, p_roleLocal);
    }
    
    private void setupConstantTables() throws NamingException {
        ChangeDeltaTypeLocalHome changeDeltaTypeLocalHome = ChangeDeltaTypeUtil.getLocalHome();
        ChangeDeltaItemTypeLocalHome changeDeltaItemTypeLocalHome = ChangeDeltaItemTypeUtil.getLocalHome();
        NotificationMechanismLocalHome notificationMechanismLocalHome = NotificationMechanismUtil.getLocalHome();
        LoginStatusLocalHome loginStatusLocalHome = LoginStatusUtil.getLocalHome();
        PermissionLocalHome permissionLocalHome = PermissionUtil.getLocalHome();
        // create the list of change delta types
        for (int i = ChangeDeltaTypeBean.NUM_TYPES - 1; i >= 0; i--) {
            try {
                changeDeltaTypeLocalHome.create(new Integer(i));
            } catch(CreateException e) {
                break;
            }
        }
        // create the list of change delta item types
        for (int i = ChangeDeltaItemTypeBean.NUM_TYPES - 1; i >= 0 ; i--) {
            try {
                changeDeltaItemTypeLocalHome.create(new Integer(i));
            } catch(CreateException e) {
                break;
            }
        }
        // create the list of notification mechanisms
        for (int i = NotificationMechanismBean.NUM_TYPES - 1; i >= 0; i--) {
            try {
                notificationMechanismLocalHome.create(new Integer(i));
            } catch(CreateException e) {
                break;
            }
        }
        // create the list of login statuses
        for (int i = LoginStatusBean.NUM_TYPES - 1; i >= 0; i--) {
            try {
                loginStatusLocalHome.create(new Integer(i));
            } catch(CreateException e) {
                break;
            }
        }
        // create the list of permissions
        for (int i = PermissionBean.NUM_TYPES - 1; i >= 0; i--) {
            try {
                if (i != PermissionBean.NOTE_CREATE && i != PermissionBean.NOTE_EDIT)
                    permissionLocalHome.create(new Integer(i));
            } catch(CreateException e) {
                break;
            }
        }
    }
    
    /**
     * Create the Session Bean.
     * @throws CreateException 
     * @ejb:create-method view-type="remote"
     */
    public void ejbCreate() throws CreateException
    {
    }

    public void ejbActivate() throws java.rmi.RemoteException {
    }
    
    public void ejbPassivate() throws java.rmi.RemoteException {
    }
    
    public void ejbRemove() throws java.rmi.RemoteException {
    }
    
    public void setSessionContext(javax.ejb.SessionContext sessionContext) throws java.rmi.RemoteException {
        m_context = sessionContext;
    }
    
}
